﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace g4
{
    /// <summary>
    /// 简单孔洞填充器：通过创建中心顶点并生成三角形扇来填充网格中的边界环孔洞
    /// 适用于简单边界环（非嵌套、无复杂拓扑）的快速填充
    /// </summary>
    public class SimpleHoleFiller
    {
        /// <summary>
        /// 包含孔洞的目标网格
        /// </summary>
        public DMesh3 Mesh;

        /// <summary>
        /// 需要填充的边界环（孔洞的边界）
        /// </summary>
        public EdgeLoop Loop;

        /// <summary>
        /// 填充时创建的中心顶点ID（仅在填充成功且顶点数>3时有效）
        /// </summary>
        public int NewVertex;

        /// <summary>
        /// 填充后新增的三角形ID数组
        /// </summary>
        public int[] NewTriangles;


        /// <summary>
        /// 构造函数：初始化简单孔洞填充器
        /// </summary>
        /// <param name="mesh">包含孔洞的目标网格</param>
        /// <param name="loop">需要填充的边界环</param>
        public SimpleHoleFiller(DMesh3 mesh, EdgeLoop loop)
        {
            Mesh = mesh;
            Loop = loop;

            NewVertex = DMesh3.InvalidID; // 初始化为无效ID
            NewTriangles = null;
        }


        /// <summary>
        /// 验证边界环是否为有效的边界环（确保可以填充）
        /// </summary>
        /// <returns>验证状态（Ok表示有效）</returns>
        public virtual ValidationStatus Validate()
        {
            return MeshValidation.IsBoundaryLoop(Mesh, Loop);
        }


        /// <summary>
        /// 执行孔洞填充操作
        /// </summary>
        /// <param name="group_id">填充三角形的组ID（-1表示使用默认组）</param>
        /// <returns>填充是否成功</returns>
        public virtual bool Fill(int group_id = -1)
        {
            // 边界环顶点数少于3，无法形成面，填充失败
            if (Loop.Vertices.Length < 3)
                return false;

            // 边界环为三角形（3个顶点）：直接添加一个三角形填充
            if (Loop.Vertices.Length == 3)
            {
                // 创建三角形（注意顶点顺序，确保法线方向正确）
                Index3i tri = new Index3i(Loop.Vertices[0], Loop.Vertices[2], Loop.Vertices[1]);
                int newTid = Mesh.AppendTriangle(tri, group_id);
                if (newTid < 0) // 三角形添加失败
                    return false;

                // 记录新增三角形，无中心顶点
                NewTriangles = new int[1] { newTid };
                NewVertex = DMesh3.InvalidID;
                return true;
            }

            // 对于4个顶点的特殊情况（可优化）：
            // [TODO] 可通过检查相邻顶点的法向量来确定最佳内部边，生成更优的两个三角形

            // 计算边界环的重心（作为填充的中心顶点）
            Vector3d centroid = Vector3d.Zero;
            foreach (int vid in Loop.Vertices)
                centroid += Mesh.GetVertex(vid);
            centroid *= 1.0 / Loop.Vertices.Length; // 平均计算重心

            // 添加重心顶点
            NewVertex = Mesh.AppendVertex(centroid);

            // 创建三角形扇：中心顶点连接边界环的每两个相邻顶点
            MeshEditor editor = new MeshEditor(Mesh);
            try
            {
                // 按顺序生成三角形扇（中心顶点 + 边界环的连续两个顶点）
                NewTriangles = editor.AddTriangleFan_OrderedVertexLoop(NewVertex, Loop.Vertices, group_id);
            }
            catch
            {
                NewTriangles = null; // 生成失败
            }

            // 填充失败时回滚：移除已添加的中心顶点
            if (NewTriangles == null)
            {
                Mesh.RemoveVertex(NewVertex, true, false);
                NewVertex = DMesh3.InvalidID;
                return false;
            }
            else
            {
                return true;
            }
        }
    }
}